package org.ogv.statemanager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class StateMgr {
	private	List<Object> 			_exchangeBuff;
	private HashMap<Integer, State> _availStates;
	private List<State> 			_activeStates;
	private int 					_toPop;
	private List<State>				_toPush;
	
	public StateMgr(State[] availStates) {
		_availStates	= new HashMap<Integer, State>();
		_activeStates 	= new ArrayList<State>();
		_toPush			= new ArrayList<State>();
		_exchangeBuff	= new LinkedList<Object>();
		_toPop			= 0;
		
		for(State state : availStates) {
			_availStates.put(state.getId(), state);
			state._stateMgr = this;
		}
	}
	
	public boolean hasActiveState() {
		return _activeStates.size() > 0;
	}
	
	public void requestPushState(int stateId) {
		requestPushState(getState(stateId));
	}
	
	public void requestPushState(State state) {
		_toPush.add(state);
	}
	
	public void requestPopState() {
		++_toPop;
	}
	
	public void run(float elapsedTime) {
		//Execute state changing requests
		while(_toPop > 0) { popState(); --_toPop;}
		for(State toPush : _toPush) pushState(toPush);
		_toPush.clear();
		
		//Update state
		State top = getTopState();
		if(top != null) top.run(elapsedTime);
	}
	
	public void pushValueInExchangeBuff(Object value) {
		_exchangeBuff.add(value);
	}
	
	public Object popValueFromExchangeBuff() {
		return _exchangeBuff.remove(_exchangeBuff.size()-1);
	}
	
	private void pushState(State req) {
		if(req == null) return;
		State top = getTopState();
		if(top != null) top.pause();
		_activeStates.add(req);
		req.init();
	}
	
	private void popState() {
		State top = getTopState();
		if(top == null) return;
		_activeStates.remove(top);
		top.destroy();
		top = getTopState();
		if(top == null) return;
		top.resume();
	}
	
	private State getTopState() {
		if(_activeStates.isEmpty()) return null;
		return _activeStates.get(_activeStates.size()-1);
	}
	
	private State getState(int stateId) {
		if(!_availStates.containsKey(stateId)) return null;
		State state = _availStates.get(stateId);
		if(_activeStates.remove(state)) state.destroy();
		return state;
	}

	public boolean hasValueInExchangeBuff() {
		return !_exchangeBuff.isEmpty();
	}
}
